package com.xinhe.web.service;

import com.alibaba.fastjson.JSONObject;
import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xinhe.web.common.BusinessException;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.*;
import com.xinhe.web.enums.*;
import com.xinhe.web.reposity.*;
import com.xinhe.web.response.OrderReturnView;
import com.xinhe.web.session.UserSessionManager;
import com.xinhe.web.util.Snowflake;
import com.xinhe.web.weixin.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
public class OrderPayService {
    //查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;

    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    @Autowired
    WeixinTradeService weixinTradeService;
    @Autowired
    OrderRepository orderRepository;
    @Autowired
    OrderItemRepository orderItemRepository;
    @Autowired
    OrderPayRepository orderPayRepository;
    @Autowired
    TeamBuyOrderService teamBuyOrderService;

    @Autowired
    MemberRepository memberRepository;
    @Autowired
    UserSessionManager userSessionManager;
    @Autowired
    AssetCountService assetCountService;
    @Autowired
    private OrderReturnRepository orderReturnRepository;

    @Transactional
    public Result saveRefund(Long orderId) {
        // APPLY("申请"), DOING("退款中"), SUCCESS("成功"), REJECT("拒绝"), CANCEL("取消");
        String status = "SUCCESS";
        OrderPay orderPay = this.orderPayRepository.findOneByOrderId(orderId);
        if (null == orderPay) {
            return Result.failed(1001, "订单没有相应付款记录，退款失败");
        }
        Result refundResult = null;
        if ("WEIXIN_JSAPI" == orderPay.getPayChannel()) {
            WeixinRefundModel wxRefundModel = new WeixinRefundModel();
            wxRefundModel.setTradeId(orderPay.getTradeId());
            wxRefundModel.setFee(orderPay.getPayMoney());
            wxRefundModel.setDataId(orderPay.getOrderId());
            wxRefundModel.setBody("订单退款");
            wxRefundModel.setNotifyUrl("/orderPay/responseWeixinRefundNotify");
            refundResult = this.weixinTradeService.requestWeixinRefund(wxRefundModel);
            status = "DOING";
            if (0 != refundResult.getCode()) {
                return Result.ok(1002, "DOING");
            } else {
                return Result.ok("SUCCESS");
            }
        } else {
            return Result.failed(1003, "订单无退款业务");
        }
    }

    @Transactional
    public Result responseOrderPayNotify() {
        System.out.println("进来支付回调了");
        Result result = this.weixinTradeService.getWeixinPayNotifyDataAndValidateAndUpdateWeixinTrade();
        if (0 != result.getCode()) {
            return result;
        }
        WeixinPayNotifyView view = (WeixinPayNotifyView) result.getData();
        WeixinTrade weixinTrade = view.getWeixinTrade();
        JSONObject orderIdsStr = JSONObject.parseObject(weixinTrade.getExtendParams());
        JSONObject jsonObject = JSONObject.parseObject(weixinTrade.getRequestInfo());
        String[] orderIds = orderIdsStr.getString("orderIdsStr").split(",");
        System.out.println("多订单id为:" + orderIds[0]);
        for (String orderId : orderIds) {
            Order order = this.orderRepository.findById(Long.valueOf(orderId)).get();
            if (order != null) {
                order.setStatus("PAYED");
                order.setOrderPayFee(order.getOrderFee());
                order.setPayTime(new Date());
                this.orderRepository.saveAndFlush(order);
                this.orderItemRepository.updateStatusByOrderId(order.getId(), "PAYED");
                this.teamBuyOrderService.savePay(order.getId());
                OrderPay orderPay = new OrderPay();
                orderPay.setPayChannel("WEIXIN_JSAPI");
                orderPay.setOrderId(order.getId());
                orderPay.setPayMoney(order.getOrderPayFee());
                orderPay.setUserId(order.getUserId());
                orderPay.setTradeId(weixinTrade.getId());
                this.orderPayRepository.save(orderPay);
            }
        }
        return Result.ok();
    }

    public QueryResults<OrderPay> pageOrderPay(Long userId, Long orderId, int pageNum, int pageSize) {
        QOrderPay qOrderPay = QOrderPay.orderPay;
        BooleanBuilder builder = new BooleanBuilder();
        if (!Objects.isNull(userId)) {
            builder.and(qOrderPay.userId.eq(userId));
        }
        if (!Objects.isNull(orderId)) {
            builder.and(qOrderPay.orderId.eq(orderId));
        }
        return queryFactory.select(
                        Projections.bean(
                                OrderPay.class,
                                qOrderPay.id,
                                qOrderPay.userId,
                                qOrderPay.orderId,
                                qOrderPay.tradeId,
                                qOrderPay.payMoney

                        )
                ).from(qOrderPay)
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();
    }

    //@ANoRepeatRequest
    @Transactional
    public Result requestPayOrder(String orderIdsStr, String payChannel) {
        String[] orderIds = orderIdsStr.split(",");
        BigDecimal orderFee = BigDecimal.ZERO;
        List<Order> orderList = this.orderRepository.findAllById((Collection) Arrays.<String>stream(orderIds).map(Long::valueOf).collect(Collectors.toSet()));
        Map<Long, Order> orderMap = (Map<Long, Order>) orderList.stream().collect(Collectors.toMap(Order::getId, order -> order));
        Member member = this.memberRepository.findByUserId(this.userSessionManager.getUserId());
        for (String orderId : orderIds) {
            Order order = orderMap.get(Long.valueOf(orderId));
            if (order == null) {
                return Result.failed(101, "订单不存在");
            }
            orderFee = orderFee.add(order.getOrderFee());
        }
        if (EPayChannel.BALANCE.equals(payChannel)) {
            AssetCount assetCount = this.assetCountService.findByTypeAndUserId("RMB", member.getFUserId()).getData();
            //认养树-运维管理费（订单总金额的%6）
            BigDecimal opexManagerFeeRate = new BigDecimal(6);
            BigDecimal opexManagerFee = orderFee.multiply(opexManagerFeeRate.multiply(new BigDecimal("0.01")));
            if (assetCount.getRemainder().compareTo(orderFee.add(opexManagerFee)) < 0) {
                return Result.failed(102, "您当前余额不足，请选择其他支付方式");
            }
            Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(((Order) orderList.get(0)).getUserId(), "RMB", "BUYER_ORDER_PAY", orderFee
                    .add(opexManagerFee).negate(), Long.valueOf(1L), "", new Date());
            if (0 != beanResult.getCode()) {
                return Result.failed(103, beanResult.getMessage());
            }
            for (Order order : orderList) {
                if ("TEAM".equals(order.getType())) {
                    order.setStatus("TEAMING");
                } else {
                    order.setStatus("PAYED");
                }
                order.setOrderPayFee(order.getOrderFee());
                order.setPayTime(new Date());
                this.orderRepository.saveAndFlush(order);
                this.orderItemRepository.updateStatusByOrderId(order.getId(), "PAYED");
                this.teamBuyOrderService.savePay(order.getId());
                OrderPay orderPay = new OrderPay();
                orderPay.setPayChannel(payChannel);
                orderPay.setOrderId(order.getId());
                orderPay.setPayMoney(order.getOrderPayFee());
                orderPay.setUserId(order.getUserId());
                this.orderPayRepository.save(orderPay);
            }
        } else {
            if (EPayChannel.WEIXIN_APP.equals(payChannel)) {
                WeixinAppPayParamModel payModel = new WeixinAppPayParamModel();
                payModel.setDataId(Long.valueOf(1L));
                payModel.setBody("订单支付");
                payModel.setFee(orderFee);
                payModel.setNotifyUrl("/orderPay/responseOrderPayNotify");
                payModel.setExtendParam("orderIdsStr", orderIdsStr);
                return this.weixinTradeService.requestWeixinPayParam(payModel);
            }
            if (EPayChannel.WEIXIN_JSAPI.equals(payChannel)) {
                WeixinJsapiPayParamModel payModel = new WeixinJsapiPayParamModel();
                payModel.setDataId(Long.valueOf(1L));
                payModel.setBody("订单支付");
                payModel.setFee(orderFee);
                payModel.setNotifyUrl("/orderPay/responseOrderPayNotify");
                Map<String, String> map = new HashMap<>();
                map.put("orderIdsStr", orderIdsStr);
                payModel.setExtendParams(map);
                return this.weixinTradeService.requestWeixinPayParam((WeixinPayParamModel) payModel);
            }
            if (EPayChannel.YUNCHASEED.equals(payChannel)) {
                AssetCount assetCount = (AssetCount) this.assetCountService.findByTypeAndUserId("YUN_CHA_SEED", member.getFUserId()).getData();
                //认养树-运维管理费（订单总金额的%6）
                BigDecimal opexManagerFeeRate = new BigDecimal(6);
                BigDecimal opexManagerFee = orderFee.multiply(opexManagerFeeRate.multiply(new BigDecimal("0.01")));
                if (assetCount.getRemainder().compareTo(orderFee.add(opexManagerFee)) < 0) {
                    return Result.failed(103, "您当前云茶籽不足，请选择其他支付方式");
                }
                Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(((Order) orderList.get(0)).getUserId(), "YUN_CHA_SEED", "BUYER_ORDER_PAY", orderFee
                        .negate(), Long.valueOf(1L), "", new Date());
                if (0 != beanResult.getCode()) {
                    return Result.failed(104, beanResult.getMessage());
                }
                for (Order order : orderList) {
                    if ("TEAM".equals(order.getType())) {
                        order.setStatus("TEAMING");
                    } else {
                        order.setStatus("PAYED");
                    }
                    order.setOrderPayFee(order.getOrderFee());
                    order.setPayTime(new Date());
                    this.orderRepository.saveAndFlush(order);
                    this.orderItemRepository.updateStatusByOrderId(order.getId(), "PAYED");
                    this.teamBuyOrderService.savePay(order.getId());
                    OrderPay orderPay = new OrderPay();
                    orderPay.setPayChannel(payChannel);
                    orderPay.setOrderId(order.getId());
                    orderPay.setPayMoney(order.getOrderPayFee());
                    orderPay.setUserId(order.getUserId());
                    this.orderPayRepository.save(orderPay);
                }
            } else if (EPayChannel.CONSUMERGOLDREDENVELOPE.equals(payChannel)) {
                AssetCount assetCount = (AssetCount) this.assetCountService.findByTypeAndUserId("CONSUMER_GOLD_RED_ENVELOPE", member.getFUserId()).getData();
                //认养树-运维管理费（订单总金额的%6）
                BigDecimal opexManagerFeeRate = new BigDecimal(6);
                BigDecimal opexManagerFee = orderFee.multiply(opexManagerFeeRate.multiply(new BigDecimal("0.01")));
                if (assetCount.getRemainder().compareTo(orderFee.add(opexManagerFee)) < 0) {
                    return Result.failed(104, "您当前消费金红包不足，请选择其他支付方式");
                }
                Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(((Order) orderList.get(0)).getUserId(),"CONSUMER_GOLD_RED_ENVELOPE","BUYER_ORDER_PAY", orderFee
                        .negate(), Long.valueOf(1L), "", new Date());
                if (0 != beanResult.getCode()) {
                    return Result.failed(104, beanResult.getMessage());
                }
                for (Order order : orderList) {
                    if ("TEAM".equals(order.getType())) {
                        order.setStatus("TEAMING");
                    } else {
                        order.setStatus("PAYED");
                    }
                    order.setOrderPayFee(order.getOrderFee());
                    order.setPayTime(new Date());
                    this.orderRepository.saveAndFlush(order);
                    this.orderItemRepository.updateStatusByOrderId(order.getId(), "PAYED");
                    this.teamBuyOrderService.savePay(order.getId());
                    OrderPay orderPay = new OrderPay();
                    orderPay.setPayChannel(payChannel);
                    orderPay.setOrderId(order.getId());
                    orderPay.setPayMoney(order.getOrderPayFee());
                    orderPay.setUserId(order.getUserId());
                    this.orderPayRepository.save(orderPay);
                }
            } else if (EPayChannel.TEAOILCARD.equals(payChannel)) {
                AssetCount assetCount = (AssetCount) this.assetCountService.findByTypeAndUserId(EAssetType.TEA_OIL_CARD.getName(), member.getFUserId()).getData();
                //认养树-运维管理费（订单总金额的%6）
                BigDecimal opexManagerFeeRate = new BigDecimal(6);
                BigDecimal opexManagerFee = orderFee.multiply(opexManagerFeeRate.multiply(new BigDecimal("0.01")));
                if (assetCount.getRemainder().compareTo(orderFee.add(opexManagerFee)) < 0) {
                    return Result.failed(105, "您当前茶油卡不足，请选择其他支付方式");
                }
                Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(((Order) orderList.get(0)).getUserId(), "TEA_OIL_CARD", "BUYER_ORDER_PAY", orderFee
                        .negate(), Long.valueOf(1L), "", new Date());
                if (0 != beanResult.getCode()) {
                    return Result.failed(106, beanResult.getMessage());
                }
                for (Order order : orderList) {
                    if ("TEAM".equals(order.getType())) {
                        order.setStatus("TEAMING");
                    } else {
                        order.setStatus("PAYED");
                    }
                    order.setOrderPayFee(order.getOrderFee());
                    order.setPayTime(new Date());
                    this.orderRepository.saveAndFlush(order);
                    this.orderItemRepository.updateStatusByOrderId(order.getId(), "PAYED");
                    this.teamBuyOrderService.savePay(order.getId());
                    OrderPay orderPay = new OrderPay();
                    orderPay.setPayChannel(payChannel);
                    orderPay.setOrderId(order.getId());
                    orderPay.setPayMoney(order.getOrderPayFee());
                    orderPay.setUserId(order.getUserId());
                    this.orderPayRepository.save(orderPay);
                }
            }
        }
        return Result.ok();
    }

    @Transactional
    public Result saveItemRefund(OrderItem orderItem) {
        OrderPay orderPay = this.orderPayRepository.findOneByOrderId(orderItem.getOrderId());
        if (null == orderPay) {
            log.error("订单{}没有相应付款记录，退款失败", orderItem.getOrderId());
            return Result.failed(101, "订单没有相应付款记录，退款失败");
        }
        if ("BALANCE" == orderPay.getPayChannel()) {
            Result beanResult = this.assetCountService.saveRemainderAsset(orderPay.getUserId(),"RMB","BUYER_ORDER_RETURN", orderItem
                    .getItemPrice(), orderItem.getId(),"",new Date());
        } else if ("WEIXIN_APP" == orderPay.getPayChannel()) {
            WeixinRefundModel wxRefundModel = new WeixinRefundModel();
            wxRefundModel.setTradeId(orderPay.getTradeId());
            wxRefundModel.setFee(orderItem.getItemPrice());
            wxRefundModel.setDataId(orderItem.getId());
            wxRefundModel.setBody("订单退款");
            wxRefundModel.setNotifyUrl("/orderPay/responseWeixinRefundOrderNotify");
            Result result = this.weixinTradeService.requestWeixinRefund(wxRefundModel);
            return Result.failed(102,"DOING");
        } else if (!"WEIXIN_JSAPI".equals(orderPay.getPayChannel())) {
            if ("YUNCHASEED".equals(orderPay.getPayChannel())) {
                Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(orderPay.getUserId(),"YUN_CHA_SEED","BUYER_ORDER_RETURN", orderPay
                        .getPayMoney(), orderPay.getOrderId(),"",new Date());
                if (0!=beanResult.getCode()) {
                    return Result.failed(103,beanResult.getMessage());
                }
            } else if ("CONSUMERGOLDREDENVELOPE".equals(orderPay.getPayChannel())) {
                Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(orderPay.getUserId(),"CONSUMER_GOLD_RED_ENVELOPE","BUYER_ORDER_RETURN", orderPay
                        .getPayMoney(), orderPay.getOrderId(),"",new Date());
                if (0!=beanResult.getCode()) {
                    return Result.failed(104,beanResult.getMessage());
                }
            } else if (EPayChannel.TEAOILCARD.equals(orderPay.getPayChannel())) {
                Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(orderPay.getUserId(),"TEA_OIL_CARD","BUYER_ORDER_RETURN", orderPay
                        .getPayMoney(), orderPay.getOrderId(),"",new Date());
                if (0!=beanResult.getCode()) {
                    return Result.failed(105,beanResult.getMessage());
                }
            } else {
                return Result.failed(106,"订单无退款业务");
            }
        }
        return Result.ok("SUCCESS");
    }

    @Transactional
    public Result requestBalancePay(Long orderId) {
        Order order = (Order) this.orderRepository.findById(orderId).get();
        if (null == order) {
            return Result.failed(101,"订单不存在");
        }
        if (!order.getStatus().equals("UN_PAY")) {
            return Result.failed(102,"订单已支付");
        }
        AssetCount assetCount = (AssetCount) this.assetCountService.findByTypeAndUserId(EAssetType.RMB.getName(), order.getUserId()).getData();
        //认养树-运维管理费（订单总金额的%6）
        BigDecimal opexManagerFeeRate = new BigDecimal(6);
        BigDecimal opexManagerFee = order.getOrderFee().multiply(opexManagerFeeRate.multiply(new BigDecimal("0.01")));
        if (assetCount.getRemainder().compareTo(order.getOrderFee().add(opexManagerFee)) < 0) {
            return Result.failed(103,"您当前余额不足，请选择其他支付方式");
        }
        order.setOpexManagerFee(opexManagerFee);
        order.setOrderFee(order.getOrderFee().add(order.getOpexManagerFee()));
        order.setOrderPayFee(order.getOrderFee());
        order.setPayTime(new Date());
        order.setPayChannel("BALANCE");
        order.setStatus("PAYED");
        this.teamBuyOrderService.savePay(order.getId());
        Result<AssetDetail> beanResult = this.assetCountService.saveRemainderAsset(order.getUserId(),"RMB", "BUYER_ORDER_PAY", order
                .getOrderPayFee().negate(), order.getId(),"",new Date());
        if (0!=beanResult.getCode()) {
            return Result.failed(104,beanResult.getMessage());
        }
        return Result.ok();
    }

    @Transactional
    public Result responseWeixinRefundOrderNotify(Long configId) {
        Result<WeixinRefundNotifyView> result = this.weixinTradeService.getWeixinRefundNotifyDataAndValidateAndUpdateWeixinTrade(configId);
        if (0!=result.getCode()) {
            return result;
        }
        WeixinRefundNotifyView refundView = result.getData();
        OrderItem orderItem = this.orderItemRepository.findById(refundView.getDataId()).get();

        if (orderItem != null) {
            orderItem.setStatus("SERVICE_SUCCESS");
            this.orderItemRepository.saveAndFlush(orderItem);

            OrderReturn orderReturn = this.orderReturnRepository.findByOrderItemIdAndStatus(orderItem.getId(),"DOING");
            if (orderReturn != null) {
                orderReturn.setStatus("SUCCESS");
                this.orderReturnRepository.saveAndFlush(orderReturn);
            }
        }
        return Result.ok();
    }

    public Result delete(Long orderPayId) {
        orderPayRepository.deleteById(orderPayId);
        return Result.ok();
    }

    public Result<OrderPay> findById(Long orderPayId) {
        return Result.ok(orderPayRepository.findById(orderPayId).get());
    }

    public Result saveModel(String orderIdsStr, String payChannel) {
        OrderPay orderPay = new OrderPay();
        orderPay.setId(Snowflake.generateId());
        orderPay.setOrderId(Long.valueOf(orderIdsStr));
        orderPay.setUserId(userSessionManager.getUserId());
        orderPay.setPayChannel(payChannel);
        orderPayRepository.save(orderPay);
        return Result.ok();
    }
}
